package com.blb.utils;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import java.lang.reflect.Field;
import java.sql.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * JDBC封装
 * @version 2.0
 */
public class DBUtils {
    private static HikariDataSource hikariDataSource;
    static {
        HikariConfig hikariConfig = new HikariConfig("/jdbc.properties");
        hikariDataSource=new HikariDataSource(hikariConfig);
        try {
            hikariDataSource.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 获取连接
     * @return
     * @throws SQLException
     */
    public  static Connection getConn() throws SQLException {
        //2.建立连接
        Connection connection = hikariDataSource.getConnection();
        return  connection;
    }
    /**
     * 设置JDBC参数
     * @param connection
     * @param sql
     * @param params
     * @return
     * @throws SQLException
     */
    private static PreparedStatement setParas(Connection connection,String sql,Object... params) throws SQLException {
        //获取执行器
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //设置参数值
        for (int i = 0; i < params.length; i++) {
            preparedStatement.setObject(i+1,params[i]);
        }
        return preparedStatement;
    }

    public static int executeUpdate(Connection connection,String sql,Object... params) throws SQLException {
        return setParas(connection,sql,params).executeUpdate();
    }

    public static <T> List<T> getList(Class<T> tClass,Connection connection,String sql,Object... params) throws SQLException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        ResultSet resultSet = setParas(connection, sql, params).executeQuery();
        ArrayList<T> list = new ArrayList<>();
        ResultSetMetaData metaData = resultSet.getMetaData();
        int columnCount = metaData.getColumnCount();
        while (resultSet.next()){
            T t = tClass.newInstance();
            for (int i = 1; i <=columnCount ; i++) {
                String columnName = metaData.getColumnName(i);
                String javaField=columnName;
                if (columnName.contains("_")){
                    String[] arr = columnName.split("_");
                    javaField=arr[0];
                    for (int j = 1; j < arr.length; j++) {
                        String s = arr[j].substring(0, 1).toUpperCase() + arr[j].substring(1);
                        javaField+=s;
                    }
                }
                Object value = null;
                if (metaData.getColumnTypeName(i).equalsIgnoreCase("DATETIME")){
                    value=resultSet.getString(i);
                }else {
                    value=resultSet.getObject(i);
                }


                Field field = tClass.getDeclaredField(javaField);
                field.setAccessible(true);
                if (metaData.getColumnTypeName(i).equalsIgnoreCase("DATETIME")){
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    LocalDateTime dateTime = LocalDateTime.from(formatter.parse(value.toString()));
                    field.set(t,dateTime);
                }else {
                    field.set(t,value);
                }
            }
            list.add(t);
        }
        return list;
    }

    public static <T> T getOne(Class<T> tClass,Connection connection,String sql,Object... params) throws SQLException, NoSuchFieldException, InstantiationException, IllegalAccessException {
        if (getList(tClass,connection,sql,params).size()==0){
            return null;
        }
        return getList(tClass,connection,sql,params).get(0);
    }

    public static ResultSet query(Connection connection,String sql,Object... params) throws SQLException {
        return setParas(connection, sql, params).executeQuery();


    }

    public static void evict(Connection conn){
        hikariDataSource.evictConnection(conn);
    }
}
